namespace Radar.Test
{
    using System.Threading;
    using NUnit.Framework;

    [TestFixture]
    public class ThreadLocalLifetimeTest
    {
        private Lifetime lifetime;

        [SetUp]
        public void SetUp()
        {
            lifetime = new ThreadLocalLifetime();
        }

        [Test]
        public void WillReturnSameInstanceForSameThread()
        {
            var builder = lifetime.GetBuilder(c => new object());

            var context = new ResolveContext();
            var o1 = builder(context);
            var o2 = builder(context);

            Assert.That(o1, Is.Not.Null);
            Assert.That(o2, Is.Not.Null);
            Assert.That(o1, Is.EqualTo(o2));
        }

        [Test]
        public void WillReturnDifferentInstancesForDifferentThreads()
        {
            var builder = lifetime.GetBuilder(c => new object());

            object o1 = null;
            object o2 = null;

            var context = new ResolveContext();
            var t1 = new Thread(delegate() { o1 = builder(context); });
            var t2 = new Thread(delegate() { o2 = builder(context); });

            t1.Start();
            t2.Start();

            t1.Join();
            t2.Join();

            Assert.That(o1, Is.Not.Null);
            Assert.That(o2, Is.Not.Null);
            Assert.That(o1, Is.Not.EqualTo(o2));
        }

        [Test]
        public void WillReturnDifferentInstancesForDifferentThreadsWithDifferentContexts()
        {
            var builder = lifetime.GetBuilder(c => c);

            object o1 = null;
            object o2 = null;
            object o3 = null;

            var context1 = new ResolveContext();
            var context2 = new ResolveContext();
            var context3 = new ResolveContext();
            var t1 = new Thread(() => o1 = builder(context1));
            var t2 = new Thread(() => o2 = builder(context2));
            var t3 = new Thread(() => o3 = builder(context3));

            t1.Start();
            t2.Start();
            t3.Start();

            t1.Join();
            t2.Join();
            t3.Join();

            Assert.That(o1 != o2);
            Assert.That(o1 != o3);
            Assert.That(o2 != o3);
        }
    }
}